using MinoChat.Ui.Enums;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace MinoChat.Ui.Controls;

//触发器监控IsOpen属性true/false控制消息通知控件的显示/隐藏
//IsOpen的回调方法中，通过计时器来确定消息通知控件的显示时间(IsOpen=false)
//暴露给外部的show方法内部设置了IsOpen=true，触发了回调方法的调用
public class Snackbar : ContentControl
{
    private DispatcherTimer? _timer;
    static Snackbar()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Snackbar), new FrameworkPropertyMetadata(typeof(Snackbar)));
    }

    #region 自定义依赖属性

    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register(nameof(Title), typeof(string), typeof(Snackbar),
            new PropertyMetadata(string.Empty));
    public string Title
    {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }
    public static readonly DependencyProperty MessageProperty =
        DependencyProperty.Register(nameof(Message), typeof(string), typeof(Snackbar),
            new PropertyMetadata(string.Empty));
    public string Message
    {
        get => (string)GetValue(MessageProperty);
        set => SetValue(MessageProperty, value);
    }
    public static readonly DependencyProperty ImageTypeProperty =
        DependencyProperty.Register(nameof(ImageType), typeof(ImageType), typeof(Snackbar),
            new PropertyMetadata(ImageType.Info));
    public ImageType ImageType
    {
        get => (ImageType)GetValue(ImageTypeProperty);
        set => SetValue(ImageTypeProperty, value);
    }
    public static readonly DependencyProperty IsOpenProperty =
        DependencyProperty.Register(nameof(IsOpen), typeof(bool), typeof(Snackbar),
            new PropertyMetadata(false, OnIsOpenChanged));
    public bool IsOpen
    {
        get => (bool)GetValue(IsOpenProperty);
        set => SetValue(IsOpenProperty, value);
    }
    public static readonly DependencyProperty DurationProperty =
        DependencyProperty.Register(nameof(Duration), typeof(int), typeof(Snackbar), new PropertyMetadata(3000));
    public int Duration
    {
        get => (int)GetValue(DurationProperty);
        set => SetValue(DurationProperty, value);
    }

    #endregion

    private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is Snackbar snackbar && (bool)e.NewValue)
        {
            snackbar.StartTimer();
        }
    }
    private void StartTimer()
    {
        _timer?.Stop();
        //DispatcherTimer是一个与UI线程绑定的定时器，它确保定时触发的事件在UI线程上执行
        //它不像传统定时器那样使用后台线程，而是将Tick事件放入UI线程的Dispatcher队列中等待执行。
        //由于是依赖UI线程的消息循环，如果UI线程繁忙Tick的执行可能会被延迟，它的精度不高(通常在10-55ms之间)
        _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(Duration) };
        // 为计时器注册事件，Tick事件是在UI线程上执行的
        _timer.Tick += (s, e) =>
        {
            _timer.Stop();
            IsOpen = false;
        };
        //启动定时器，Tick事件在一定时间Interval后自动执行
        _timer.Start();
    }
    //暴露给外部的show方法内部设置了IsOpen=true，触发了回调方法的调用
    public void Show(string title, string message, ImageType type = ImageType.Info, int duration = 3000)
    {
        Title = title;
        Message = message;
        ImageType = type;
        Duration = duration;
        IsOpen = true;
    }
}